import SCons
import os
import distutils.sysconfig

def ENV_update(tgt_ENV, src_ENV):
    for K in src_ENV.keys():
        if K in tgt_ENV.keys() and K in [ 'PATH', 'LD_LIBRARY_PATH',
                                          'LIB', 'INCLUDE' ]:
            tgt_ENV[K]=SCons.Util.AppendPath(tgt_ENV[K], src_ENV[K])
        else:
            tgt_ENV[K]=src_ENV[K]

ENV = os.environ
# XXX: yuck
TOOLS = ENV.get('TOOLS')
if TOOLS is not None:
    TOOLS = TOOLS.split(',') or None
common = Environment(tools=TOOLS)
common.SConsignFile()

ENV_update(common['ENV'], ENV)

CC = common['CC']
PLATFORM = common['PLATFORM']

CONFIG_FILE = 'config.%s.%s.opts' % (PLATFORM, CC)
if not os.path.exists(CONFIG_FILE):
    print '*** ERROR: There is no configuration file available for your system configuration. (PLATFORM: %r, CC: %r)' % (PLATFORM, CC)
    Exit(1)
print '*** Using config file %r...' % (CONFIG_FILE,)

if PLATFORM == 'win32':
    CONFIG_GUESS = 'windows'
else:
    ENV['SRCHOME'] = 'source/'
    cmd = ENV.get('SHELL', 'sh') + ' source/tools/guess/guessconfig'
    CONFIG_GUESS = os.popen(cmd).read()[:-1]

def makeBuiltinLibPath(libname, path):
    paths = ['#../lib/%s/%s/%s' % (CONFIG_GUESS, libname, path)]
    if CC in ('gcc'):
        paths += ['#../lib/%s/gcc/%s/%s' % (CONFIG_GUESS, libname, path)]
    return paths
# XXX: good grief! i'm lazy
mbilp = makeBuiltinLibPath

options = Options(CONFIG_FILE)
options.AddOptions(
    ('VERSION', 'The version number to use', '2.37a'),
    ('BUILD_DIR', 'The build directory', '..\\obuild'),
    ('NEW_CSG', 'Use the new CSG library', False),
    ('BINARY_BLENDER_NAME', 'The filename of the blender binary', 'blender'),
    ('BINARY_PLAYER_NAME', 'The filename of the blenderplayer binary', 'blenderplayer'),
    ('USE_BUILDINFO', 'Generate build info', True),
    ('USE_CCGSUBSURFLIB', 'Use CCG sub-surface', True),
    ('USE_INTERNATIONAL', 'Use international language support', True),
    ('USE_FMOD', 'Use FMOD for sound', False),
    ('USE_OPENAL', 'Use OpenAL for sound', False),
    ('USE_QUICKTIME', 'Use QuickTime', False),
    ('BUILD_GAMEENGINE', 'Build the game engine', True),
    ('RELEASE_FLAGS', 'Release build flags', []),
    ('DEBUG_FLAGS', 'Debug build flags', []),
    ('WARN_FLAGS', 'Warning flags', []),
    ('EXTRA_FLAGS', 'Extra compiler flags', []),
    ('CCFLAGS', 'Extra compiler flags'),
    ('DEBUG', 'Build debug binary', False),
    ('CONFIG_GUESS', 'Guessed configuration', CONFIG_GUESS),
    EnumOption('WINDOW_SYSTEM', 'Windowing system', 'x11', allowed_values=('x11', 'win32', 'carbon')),
    EnumOption('USE_PHYSICS', 'Physics library to use', 'solid', allowed_values=['solid', 'bullet', 'ode']),
    ('BULLET_INCLUDE', 'Bullet include path', ['#extern/bullet', '#extern/bullet/LinearMath', '#extern/bullet/Bullet', '#extern/bullet/BulletDynamics']),
    ('SOLID_INCLUDE', 'Solid include path', ['#extern/solid']),
    # XXX: darwin needs hax
    ('FTGL_INCLUDE', 'FreeTypeGL include path', ['#extern/bFTGL/include']),
    ('FTGL_LIBPATH', 'FreeTypeGL library path', []),
    ('FTGL_LIBRARY', 'FreeTypeGL library names'),
    ('OPENGL_INCLUDE', 'OpenGL include path', []),
    ('OPENGL_LIBPATH', 'OpenGL library path', []),
    ('OPENGL_LIBRARY', 'OpenGL library names'),
    ('OPENAL_INCLUDE', 'OpenAL include path', []),
    ('OPENAL_LIBPATH', 'OpenAL library path', []),
    ('OPENAL_LIBRARY', 'OpenAL library names'),
    ('QUICKTIME_INCLUDE', 'QuickTime include path', []),
    ('QUICKTIME_LIBPATH', 'QuickTime library path', []),
    ('QUICKTIME_LIBRARY', 'QuickTime library names'),
    ('ODE_INCLUDE', 'ODE include path', []),
    ('ODE_LIBPATH', 'ODE library path', []),
    ('ODE_LIBRARY', 'ODE library names'),
    ('PYTHON_INCLUDE', 'Python include path', [distutils.sysconfig.get_python_inc()]),
    ('PYTHON_LIBPATH', 'Python library path', []),
    ('PYTHON_LIBRARY', 'Python library names', ['python' + distutils.sysconfig.get_python_version()]),
    ('JPEG_INCLUDE', 'JPEG include path', mbilp('jpeg', 'include')),
    ('JPEG_LIBPATH', 'JPEG library path', mbilp('jpeg', 'lib')),
    ('JPEG_LIBRARY', 'JPEG library names'),
    ('PNG_INCLUDE', 'PNG include path', mbilp('png', 'include')),
    ('PNG_LIBPATH', 'PNG library path', mbilp('png', 'lib')),
    ('PNG_LIBRARY', 'PNG library names'),
    ('PLATFORM_LIBPATH', 'Platform specific library path', []),
    ('PLATFORM_LIBS', 'Platform specific library names', []),
    ('PLATFORM_LINKFLAGS', 'Platform specific linker flags', []),
    ('PLATFORM_DEFINES', 'Platform specific #defines', []),
    ('GETTEXT_INCLUDE', 'gettext include path', []),
    ('GETTEXT_LIBPATH', 'gettext library path', []),
    ('GETTEXT_LIBRARY', 'gettext library names', []),
    ('Z_INCLUDE', 'Zlib include path', mbilp('zlib', 'include')),
    ('Z_LIBPATH', 'Zlib library path', mbilp('zlib', 'lib')),
    ('Z_LIBRARY', 'Zlib library names'),
    ('SDL_INCLUDE', 'SDL include path', mbilp('sdl', 'include')),
    ('SDL_LIBPATH', 'SDL library path', mbilp('sdl', 'lib')),
    ('SDL_LIBRARY', 'SDL library name', ['SDL']),
    ('FREETYPE_INCLUDE', 'FreeType include path', []),
    ('FREETYPE_LIBPATH', 'FreeType library path', []),
    ('FREETYPE_LIBRARY', 'FreeType library names'),
    # XXX: this is a hack
    #('BUILD_BLENDER_PLAYER', 'Build blenderplayer', 'blenderplayer' in COMMAND_LINE_TARGETS),
)

options.Update(common)
Export('options')
#Help(options.GenerateHelpText(common))

print 'YYY', common['CONFIG_GUESS']
print 'ZZZ', common['SDL_INCLUDE'], common['SDL_LIBPATH']

CCFLAGS = common['WARN_FLAGS'] + common['EXTRA_FLAGS']
if common['DEBUG']:
    CCFLAGS += common['DEBUG_FLAGS']
else:
    CCFLAGS += common['RELEASE_FLAGS']

common.Append(
    CCFLAGS=CCFLAGS,
    LDFLAGS=common['PLATFORM_LINKFLAGS'],
    CPPDEFINES=common['PLATFORM_DEFINES'],
)
common.Append(LINKFLAGS = '$PLATFORM_LINKFLAGS')

# XXX: it is kinda eww to have to put this stuff here, but option files get nothing that will make this cleaner *sigh*
sdlEnv = common.Copy()
freetypeEnv = common.Copy()

# -- SDL --
if CC in ('gcc',):
    sdlEnv.ParseConfig('sdl-config --cflags --libs')
    common['SDL_INCLUDE'] = sdlEnv['CPPPATH']
    common['SDL_LIBPATH'] = sdlEnv['LIBPATH']
    common['SDL_LIBRARY'] = sdlEnv['LIBS']
else:
    # do something clever
    pass
Export('sdlEnv')

# -- FreeType --
if CC in ('gcc',):
    freetypeEnv.ParseConfig('pkg-config --cflags --libs freetype2 2>/dev/null || freetype-config --cflags --libs 2>/dev/null')
    common['FREETYPE_INCLUDE'] = freetypeEnv['CPPPATH']
    common['FREETYPE_LIBPATH'] = freetypeEnv['LIBPATH']
    common['FREETYPE_LIBRARY'] = freetypeEnv['LIBS']
else:
    # do something clever
    pass
Export('freetypeEnv')

commonLibs = [
    ('#$BUILD_DIR/lib', 'blender_readblenfile'),
    ('#$BUILD_DIR/lib', 'blender_img'),
    ('#$BUILD_DIR/lib', 'blender_blenkernel'),
    ('#$BUILD_DIR/lib', 'blender_blenloader'),
    ('#$BUILD_DIR/lib', 'blender_blenpluginapi'),
    ('#$BUILD_DIR/lib', 'blender_imbuf'),
    ('#$BUILD_DIR/lib', 'blender_avi'),
    ('#$BUILD_DIR/lib', 'blender_blenlib'),
    ('#$BUILD_DIR/lib', 'blender_makesdna'),
    ('#$BUILD_DIR/lib', 'blender_kernel'),
    ('#$BUILD_DIR/lib', 'blender_ghost'),
    ('#$BUILD_DIR/lib', 'blender_string'),
    ('#$BUILD_DIR/lib', 'blender_guardedalloc'),
    ('#$BUILD_DIR/lib', 'blender_container'),
    ('#$BUILD_DIR/lib', 'blender_memutil'),
    ('#$BUILD_DIR/lib', 'blender_moto'),
    ('#$BUILD_DIR/lib', 'blender_bmfont'),
    ('#$BUILD_DIR/lib', 'blender_soundsystem'),
    common['USE_QUICKTIME'] and
        ('#$BUILD_DIR/lib', 'blender_quicktime') or
        None,
]

blenderLibs = [
    ('#$BUILD_DIR/lib', 'blender_creator'),
    ('#$BUILD_DIR/lib', 'blender_src'),
    ('#$BUILD_DIR/lib', 'blender_render'),
    ('#$BUILD_DIR/lib', 'blender_yafray'),
    ('#$BUILD_DIR/lib', 'blender_renderconverter'),
    ('#$BUILD_DIR/lib', 'blender_radiosity'),
    common['NEW_CSG'] and
        ('#$BUILD_DIR/lib', 'blender_csg') or
        ('#$BUILD_DIR/lib', 'blender_bsp'),
    ('#$BUILD_DIR/lib', 'blender_blenkernel'),
    ('#$BUILD_DIR/lib', 'blender_decimation'),
    ('#$BUILD_DIR/lib', 'blender_iksolver'),
    ('#$BUILD_DIR/lib', 'blender_opennl'),
    ('#$BUILD_DIR/lib', 'blender_elbeem'),
    ('#$BUILD_DIR/lib', 'blender_bop'),
]

internationalLibs = []
if common['USE_INTERNATIONAL']:
    internationalLibs.extend([
        #(common['FREETYPE_LIBPATH'], common['FREETYPE_LIBRARY']),
        ('$FREETYPE_LIBPATH', '$FREETYPE_LIBRARY'),
        ('#$BUILD_DIR/lib', 'blender_ftfont'),
        ('#$BUILD_DIR/lib', 'extern_ftgl'),
        ('$FREETYPE_LIBPATH', '$FREETYPE_LIBRARY'),
        PLATFORM == 'darwin' and 
            (common['FTGL_LIBPATH'], common['FTGL_LIBRARY']) or
            ('#$BUILD_DIR/lib', 'extern_ftgl'),
        #(None, common['FREETYPE_LIBRARY']),
    ])

gameEngineLibs = []
if common['BUILD_GAMEENGINE']:
    gameEngineLibs.extend([
        ('#$BUILD_DIR/lib', 'KX_blenderhook'),
        ('#$BUILD_DIR/lib', 'KX_converter'),
        ('#$BUILD_DIR/lib', 'PHY_Dummy'),
        ('#$BUILD_DIR/lib', 'PHY_Physics'),
        ('#$BUILD_DIR/lib', 'KX_ketsji'),
        ('#$BUILD_DIR/lib', 'SCA_GameLogic'),
        ('#$BUILD_DIR/lib', 'RAS_rasterizer'),
        ('#$BUILD_DIR/lib', 'RAS_OpenGLRasterizer'),
        ('#$BUILD_DIR/lib', 'blender_expressions'),
        ('#$BUILD_DIR/lib', 'SG_SceneGraph'),
        ('#$BUILD_DIR/lib', 'blender_moto'),
        ('#$BUILD_DIR/lib', 'KX_blenderhook'),
        ('#$BUILD_DIR/lib', 'KX_network'),
        ('#$BUILD_DIR/lib', 'blender_kernel'),
        ('#$BUILD_DIR/lib', 'NG_network'),
        ('#$BUILD_DIR/lib', 'NG_loopbacknetwork'),
    ])

    if common['USE_PHYSICS'] == 'solid':
        gameEngineLibs.extend([
            ('#$BUILD_DIR/lib', 'PHY_Sumo'),
            ('#$BUILD_DIR/lib', 'PHY_Bullet'),
            ('#$BUILD_DIR/lib', 'PHY_Physics'),
            ('#$BUILD_DIR/lib', 'blender_moto'),
            ('#$BUILD_DIR/lib', 'extern_solid'),
            ('#$BUILD_DIR/lib', 'extern_qhull'),
            ('#$BUILD_DIR/lib', 'extern_bullet'),
        ])
    elif common['USE_PHYSICS'] == 'bullet':
        # XXX: copied from the old build system, but this doesn't compile...i guess someone never checked this
        gameEngineLibs.extend([
            ('#$BUILD_DIR/lib', 'PHY_Bullet'),
            ('#$BUILD_DIR/lib', 'PHY_Physics'),
            ('#$BUILD_DIR/lib', 'blender_moto'),
            ('#$BUILD_DIR/lib', 'extern_bullet'),
        ])
    else:
        gameEngineLibs.extend([
            ('#$BUILD_DIR/lib', 'PHY_Ode'),
            ('#$BUILD_DIR/lib', 'PHY_Physics'),
            ('#$BUILD_DIR/lib', 'blender_moto'),
            ('#$BUILD_DIR/lib', 'extern_bullet'),
            (env['ODE_LIBPATH'], env['ODE_LIBRARY']),
        ])

playerLibs = [
    ('#$BUILD_DIR/lib', 'GPG_ghost'),
    ('#$BUILD_DIR/lib', 'GPC_common'),
]

playerLibs2 = [
    ('#$BUILD_DIR/lib', 'blender_blenkernel_blc'),
    ('#$BUILD_DIR/lib', 'blender_decimation'),
    ('#$BUILD_DIR/lib', 'blender_soundsystem'),
]

systemLibs = [
    (common['PYTHON_LIBPATH'], common['PYTHON_LIBRARY']),
    (common['JPEG_LIBPATH'], common['JPEG_LIBRARY']),
    (common['PNG_LIBPATH'], common['PNG_LIBRARY']),
    (common['SDL_LIBPATH'], common['SDL_LIBRARY']),
    (common['OPENGL_LIBPATH'], common['OPENGL_LIBRARY']),
    ('$FREETYPE_LIBPATH', '$FREETYPE_LIBRARY'),
    ('$FTGL_LIBPATH', '$FTGL_LIBRARY'),
    ('$GETTEXT_LIBPATH', '$GETTEXT_LIBRARY'),
    ('$Z_LIBPATH', '$Z_LIBRARY'),
    (common['PLATFORM_LIBPATH'], common['PLATFORM_LIBS']),
    common['USE_QUICKTIME'] and
        (common['QUICKTIME_LIBPATH'], common['QUICKTIME_LIBRARY']) or
        None,
]

#common.Prepend(LIBS = '$FREETYPE_LIBRARY')

def buildLib(name, duplicate=True):
    env = common.Copy(BUILD_NAME=name)
    Export('env')
    print "reading %s" % name
    return env.SConscript('#$BUILD_NAME/SConscript', build_dir='#$BUILD_DIR/$BUILD_NAME', duplicate=duplicate)

def realiseLibPairs(env, pairs):
    LIBPATH, LIBS = map(Flatten, zip(*[pair for pair in pairs if pair]))
    env.Append(LIBPATH=LIBPATH, LIBS=LIBS)

def emitBuildInfo(env):
    import time
    
    print "build info"

    if not common['USE_BUILDINFO']:
        return []
    
    build_date = time.strftime ("%Y-%m-%d")
    build_time = time.strftime ("%H:%M:%S")

    if PLATFORM == 'win32':
        build_info_file = open("source/creator/winbuildinfo.h", 'w')
        build_info_file.write("char *build_date=\"%s\";\n"%build_date)
        build_info_file.write("char *build_time=\"%s\";\n"%build_time)
        build_info_file.write("char *build_platform=\"win32\";\n")
        build_info_file.write("char *build_type=\"dynamic\";\n")
        build_info_file.close()
        env.Append (CPPDEFINES = ['NAN_BUILDINFO', 'BUILD_DATE'])
    else:
        env.Append(CPPDEFINES={
            'BUILD_TIME': time.strftime('\'"%Y-%m-%d"\''),
            'BUILD_DATE': time.strftime('\'"%H:%M:%S"\''),
            'BUILD_TYPE': '\'"dynamic"\'',
            'BUILD_PLATFORM': '\'"%s"\'' % (PLATFORM,),
            'NAN_BUILDINFO': None,
        }.items())
    return [env.Object('source/creator/buildinfo.c')]

print '*** %s build' % ('Release', 'Debug')[bool(common['DEBUG'])]
buildLib('intern')
buildLib('extern')
buildLib('source')

libs = commonLibs + internationalLibs + gameEngineLibs + systemLibs
buildInfo = emitBuildInfo(common)

binary = common.Copy()
#x = binary['ENV']
#for k in x:
#    print "--> ", k, " = ", x[k]
realiseLibPairs(binary, libs + blenderLibs + [('#$BUILD_DIR/source/blender/python', 'blender_python')])
blender = binary.Program('blender', source=buildInfo)

binary = common.Copy()
realiseLibPairs(binary, libs + playerLibs + playerLibs2)
blenderplayer = binary.Program('blenderplayer', source=buildInfo)

Default(blender)
if common['BUILD_GAMEENGINE']:
    Default(blenderplayer)
